#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <dirent.h>
#include <unistd.h>
#include <vector>
#include <sstream>
#include <fstream>
#include <sys/io.h>
#include <sys/times.h>
#include <iomanip> // setw()
using namespace std;

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;

cv::Mat generateA5(int number);
cv::Mat generateA4(int number);
cv::Mat generateA4Color(int number);
cv::Mat pitch(int num1, int num2);
cv::Mat generateA45Edge(int number);

#define PAPER_A5 		0
#define PAPER_A4 		1
#define PAPER_A4_COLOR 	2
#define PAPER_A4_5EDGE 	3

int main(int argc, char** argv)
{
	cout << ">> ----" << "\n" << endl;

	switch (PAPER_A4_5EDGE) {
	case PAPER_A5: {
		cv::Mat img1 = pitch(12, 3);
		cv::Mat img2 = pitch(4, 56);
		cv::Mat img3 = pitch(78,90);
		cv::Mat img4 = pitch(11,23);
		cv::Mat img5 = pitch(45,69);
		cv::Mat img6 = pitch(96,90);
		cv::imwrite("./z1.jpg", img1);
		cv::imwrite("./z2.jpg", img2);
		cv::imwrite("./z3.jpg", img3);
		cv::imwrite("./z4.jpg", img4);
		cv::imwrite("./z5.jpg", img5);
		cv::imwrite("./z6.jpg", img6);
		break;
	}
	case PAPER_A4: {
		cv::Mat img1 = generateA4(610);
		cv::Mat img2 = generateA4(234);
		cv::Mat img3 = generateA4(456);
		cv::Mat img4 = generateA4(567);
		cv::Mat img5 = generateA4(698);
		cv::Mat img6 = generateA4(980);
		cv::imwrite("./z1.jpg", img1);
		cv::imwrite("./z2.jpg", img2);
		cv::imwrite("./z3.jpg", img3);
		cv::imwrite("./z4.jpg", img4);
		cv::imwrite("./z5.jpg", img5);
		cv::imwrite("./z6.jpg", img6);
		break;
	}
	case PAPER_A4_COLOR: {
		cv::Mat img1 = generateA4Color(1);
		cv::Mat img2 = generateA4Color(12);
		cv::Mat img3 = generateA4Color(456);
		cv::Mat img4 = generateA4Color(567);
		cv::Mat img5 = generateA4Color(698);
		cv::Mat img6 = generateA4Color(980);
		cv::imwrite("./z1.jpg", img1);
		cv::imwrite("./z2.jpg", img2);
		cv::imwrite("./z3.jpg", img3);
		cv::imwrite("./z4.jpg", img4);
		cv::imwrite("./z5.jpg", img5);
		cv::imwrite("./z6.jpg", img6);
		break;
	}
	case PAPER_A4_5EDGE: {
		cv::Mat img1 = generateA45Edge(1);
		cv::Mat img2 = generateA45Edge(12);
		cv::Mat img3 = generateA45Edge(456);
		cv::Mat img4 = generateA45Edge(567);
		cv::Mat img5 = generateA45Edge(698);
		cv::Mat img6 = generateA45Edge(980);
		cv::imwrite("./z1.jpg", img1);
		cv::imwrite("./z2.jpg", img2);
		cv::imwrite("./z3.jpg", img3);
		cv::imwrite("./z4.jpg", img4);
		cv::imwrite("./z5.jpg", img5);
		cv::imwrite("./z6.jpg", img6);
		break;
	}
	}
	
	cout << "\n" << ">> ----" << endl;
	return 0;
}

cv::Mat generateA5(int number) {
	cv::Mat src = cv::Mat(cv::Size(920, 700), CV_8UC3, Scalar::all(255));
	int nEdge = 50;
	int nThickness = 50;
	cv::Rect outerRect(nEdge, nEdge, src.cols - nEdge * 2, src.rows - nEdge * 2);
	cv::rectangle(src, outerRect, cv::Scalar(0,0,0), -1, 8, 0);
	cv::Rect innerRect(nEdge + nThickness, nEdge + nThickness, 
	src.cols - (nEdge + nThickness) * 2, src.rows - (nEdge + nThickness) * 2);
	cv::rectangle(src, innerRect, cv::Scalar(255,255,255), -1, 8, 0);
/*	cv::rectangle(src, 
	              cv::Point(nEdge + nThickness, nEdge + nThickness), 
	              cv::Point(nEdge + nThickness*2, nEdge + nThickness*2),
	  		 	  cv::Scalar(0,0,0), -1, 8, 0); */
	cv::Point pt[3];
	pt[0] = cv::Point(innerRect.x, innerRect.y);
	pt[1] = cv::Point(innerRect.x + nThickness*2, innerRect.y);
	pt[2] = cv::Point(innerRect.x, innerRect.y + nThickness*2);
	cv::fillConvexPoly(src, pt, 3, cv::Scalar(0,0,0), 8, 0);
	stringstream ss;
	ss << number;
	string str = ss.str();
	cv::putText(src, str, 
	   			cv::Point(nEdge + nThickness*2.2, src.rows - nEdge - nThickness*2.7), 
	   			CV_FONT_HERSHEY_DUPLEX,
				15, Scalar(0), 48, 8, false);
/*	namedWindow("win");
	imshow("win", src);
	waitKey(0);
	cv::imwrite("./z.jpg", src);*/
	return src;
}


cv::Mat generateA4(int number) {
	cv::Mat src = cv::Mat(cv::Size(1300, 900), CV_8UC3, Scalar::all(255));
	int nEdge = 50;
	int nThickness = 80;
	cv::Rect outerRect(nEdge, 
					   nEdge, 
					   src.cols - nEdge * 2, 
					   src.rows - nEdge * 2);
	cv::rectangle(src, outerRect, cv::Scalar(0,0,0), -1, 8, 0);
	cv::Rect innerRect(nEdge + nThickness, nEdge + nThickness, 
	src.cols - (nEdge + nThickness) * 2, src.rows - (nEdge + nThickness) * 2);
	cv::rectangle(src, innerRect, cv::Scalar(255,255,255), -1, 8, 0);
	cv::Point pt[3];
	pt[0] = cv::Point(innerRect.x, innerRect.y);
	pt[1] = cv::Point(innerRect.x + nThickness*3, innerRect.y);
	pt[2] = cv::Point(innerRect.x, innerRect.y + nThickness*3);
	cv::fillConvexPoly(src, pt, 3, cv::Scalar(0,0,0), 8, 0);
	stringstream ss;
	ss << number;
	string str = ss.str();
	cv::putText(src, str, 
	   			cv::Point(nEdge + nThickness*3, src.rows - nEdge - nThickness*3), 
	   			CV_FONT_HERSHEY_DUPLEX,
				15, Scalar(0), 48, 8, false);
	cv::rotate(src, src, 90);
//	namedWindow("win");
//	imshow("win", src);
	waitKey(0);
	return src;
}

cv::Mat generateA4Color(int number) {
	cv::Mat src = cv::Mat(cv::Size(1180, 800), CV_8UC3, Scalar::all(255));
	int nEdge = 60;
	int nThickness = 70;
	cv::Rect outerRect(nEdge, 
					   nEdge, 
					   src.cols - nEdge * 2, 
					   src.rows - nEdge * 2);
	cv::rectangle(src, outerRect, cv::Scalar(200, 0, 0), -1, 8, 0);

	cv::Rect innerRect(nEdge + nThickness, 
					   nEdge + nThickness, 
					   src.cols - (nEdge + nThickness) * 2, 
					   src.rows - (nEdge + nThickness) * 2);
	cv::rectangle(src, innerRect, cv::Scalar(255,255,255), -1, 8, 0);
	
	cv::Rect BottomLine(innerRect.x + nEdge, 
						innerRect.y + innerRect.height - nEdge * 2, 
						innerRect.width - nEdge * 2, 
						nEdge);
	cv::rectangle(src, BottomLine, cv::Scalar(0,0,0), -1, 8, 0);
	
	cv::Rect BottomRect(outerRect.x, 
						innerRect.y + innerRect.height, 
						outerRect.width, 
						nThickness);
	cv::rectangle(src, BottomRect, cv::Scalar(0, 0, 200), -1, 8, 0);
	
	if (number <= 0 || number > 999) {
		cout << ">> error. number is out of range. " << endl;
		return cv::Mat();
	}
	for (int i = 0; i < 3; i++) {
		cv::Point pt(BottomLine.x + i * (BottomLine.width - nEdge * 2) / 3 + nEdge * i, 
					 BottomLine.y - nEdge * 1.3);
		if (i == 1)
			cv::rectangle(src, Rect(pt.x - nEdge + 6, BottomLine.y, nEdge, nEdge), 
						  cv::Scalar(255, 255, 255), -1, 8, 0); 
		int a  = number / (int)pow(10., 2. - i);
		number = number % (int)pow(10., 2. - i);
		stringstream ss;
		if (a > 0) 
			ss << a;
		else
			ss << 0;
		string str = ss.str();
		cv::putText(src, str, pt, CV_FONT_HERSHEY_DUPLEX, 12, Scalar(0), 40, LINE_8, false);
	}
	cv::rotate(src, src, 90);
/*	namedWindow("win");
	imshow("win", src);
	waitKey(0);*/
	return src;
}

cv::Mat generateA45Edge(int number) {
	cv::Mat src = cv::Mat(cv::Size(1180, 800), CV_8UC3, Scalar::all(255));
	int nEdge = 60;
	int nThickness = 70;
	cv::Rect outerRect(nEdge, 
					   nEdge, 
					   src.cols - nEdge * 2, 
					   src.rows - nEdge * 2);
	cv::rectangle(src, outerRect, cv::Scalar(0, 0, 0), -1, 8, 0);

	cv::Rect innerRect(nEdge + nThickness, 
					   nEdge + nThickness, 
					   src.cols - (nEdge + nThickness) * 2, 
					   src.rows - (nEdge + nThickness) * 2);
	cv::rectangle(src, innerRect, cv::Scalar(255,255,255), -1, 8, 0);
	
	cv::Point pt[4];
	pt[0] = cv::Point(innerRect.x, innerRect.y + innerRect.height * 0.3);
	pt[1] = cv::Point(innerRect.x + innerRect.height * 0.3, innerRect.y);
	pt[2] = cv::Point(pt[1].x - nThickness/2.5, pt[1].y - nThickness);
	pt[3] = cv::Point(pt[0].x - nThickness, pt[0].y - nThickness/2.5);
	cv::fillConvexPoly(src, pt, 4, cv::Scalar(0,0,0), 8, 0);

	cv::Point pt1[3];
	pt1[0] = cv::Point(outerRect.x, outerRect.y);
	pt1[1] = pt[3];
	pt1[2] = pt[2];
	cv::fillConvexPoly(src, pt1, 3, cv::Scalar(255,255,255), 8, 0);

	
	if (number <= 0 || number > 999) {
		cout << ">> error. number is out of range. " << endl;
		return cv::Mat();
	}
	cv::Rect BottomLine(innerRect.x + nThickness, innerRect.y + innerRect.height - nThickness / 2, 
	innerRect.width - 2*nThickness, nThickness);
	for (int i = 0; i < 3; i++) {
		cv::Point pt(BottomLine.x + i * (BottomLine.width - nEdge * 2) / 3 + nEdge * i, 
					 BottomLine.y - nEdge * 1.3);
		int a  = number / (int)pow(10., 2. - i);
		number = number % (int)pow(10., 2. - i);
		stringstream ss;
		if (a > 0) 
			ss << a;
		else
			ss << 0;
		string str = ss.str();
		cv::putText(src, str, pt, CV_FONT_HERSHEY_DUPLEX, 12, Scalar(0), 40, LINE_8, false);
	}
	cv::rotate(src, src, 90);
/*	namedWindow("win");
	imshow("win", src);
	waitKey(0);*/
	return src;
}

cv::Mat pitch(int num1, int num2) {
	std::vector<cv::Mat> matrices = {generateA5(num1), generateA5(num2)};
	cv::Mat out;
	cv::vconcat(matrices, out);
	return out;
}

